#!/usr/bin/env python2.5
# -*- coding: UTF-8 -*-   
__author__ = "Nick Milon"
#notes
# for qupta read  http://blog.notdot.net/2010/08/New-in-1-3-6-Namespaces

## lazy imports ##
mdlsCntrs = None   
simplejson=None 
logging = None 
NMhtml = None
#from nmpacks.milonpy import NMhtml 
#################

import modelsIP 
from google.appengine.ext import webapp 
from google.appengine.ext.webapp.util import run_wsgi_app 
from google.appengine.api import memcache 
# Note: temporary
# /api/geolocation/ip/format/
# /api/countries/cc/format/ 

MdlCache = None
import logging # logging = None for no logging

class cacheDic(object):
    casheDic={} 
    def __init__(self, namespace="", maxDicItems=100):  
        self.maxDicItems=maxDicItems 
    def get(self, key):return self.casheDic.get(key, None)  
    def set (self,key, val):
        if len(self.casheDic) > self.maxDicItems:self.casheDic={}  
        self.casheDic[key]=val   

class cashe3(object):
    casheDic={}
    #cacheType     0 = nocashe, 1=Dictionary Cashe, 2=Memcache,4=big Table cashe, 7=all
    #namespace="foo"
    def __init__(self, namespace=None, maxDicItems=300): 
        self.namespace=namespace
        self.maxDicItems=maxDicItems 
    def get(self, key): 
        casheDicKey=key # "%s-%s" %(self.namespace, key)
        rt=self.casheDic.get(casheDicKey, None) 
        if rt is None:
            if logging:logging.info('cashe-dic Fail')
            rt=memcache.get(key) 
            if rt is None:
                if logging:logging.info('cashe-mem Fail') 
                global MdlCache 
                if  MdlCache is None:from nmpacks.milonpy.cachedb import MdlCache  
                rt= MdlCache.get(key)
                if rt is None:
                    if logging:logging.info('cashe-db Fail') 
                else:    
                    rt=rt.val
                    memcache.set(key, rt)
                    self.casheDic[casheDicKey]=rt
                return rt  
            else:
                if len(self.casheDic) > self.maxDicItems:self.casheDic={} 
                self.casheDic[casheDicKey]=rt 
                return rt   
        else:
            return rt
    def set (self,key, val, cacheType=None): 
        if len(self.casheDic) > self.maxDicItems:self.casheDic={}
        casheDicKey= key #"%s-%s" %(self.namespace, key)
        self.casheDic[casheDicKey]=val 
        memcache.set(key, val)  
        global MdlCache
        if  MdlCache is None:from nmpacks.milonpy.cachedb import MdlCache
        MdlCache.setDeferred(key, val)
        
cashe3RHD=cashe3()
 
#class RHgeoip(webapp.RequestHandler):  
#    def get(self, reqtp ):
#        if reqtp=='geolocation':
#           ipStr=self.request.get('ip', None)
#           if ip is None:ipStr=self.request.remote_addr
#        if ip:
#            ipNum= modelsip.NMinet.IPencode(ip)
#            rt=modelsip.ipv4.getItemFromIpInt(ipNum)
#            if rt is None:
#                self.response.out.write("not Found:" +ip)
#            else:
#                self.response.out.write(rt.cc)   
#        else:
#            self.response.out.write("no ip")   
#        return 
        
def makeHtml(entity, req ):
    def frmtF(l):return  str(["%.2f" %n for n in l]).replace("'", "").replace('[', '').replace(']', "")
    global NMhtml
    if NMhtml is None: from nmpacks.milonpy import NMhtml  
    def entityHtml(entity):
        infoTitle="World Countries : %s" %(entity.Name)
        EntCapital=entity.Capital
        mapUrl="http://maps.google.com/maps/api/staticmap?size=300x200&&sensor=false&path=weight:3|fillcolor:"
        mapUrl="%s|%.2f,%.2f|%.2f,%.2f|%.2f,%.2f|%.2f,%.2f|%.2f,%.2f" %(mapUrl, entity.RectN, entity.RectW,entity.RectN, entity.RectE,entity.RectS,
                                                                        entity.RectE, entity.RectS, entity.RectW,  entity.RectN, entity.RectW)  

#      http://localhost:8080/media/flags/world-countries-flags-160X80.png 
#      <p class="nm-flg" style="background-position: -2320px" title="Brazil"></p>
        countryFlag =NMhtml.p() 
        countryFlag.attrSetClass("gn-flag")
        countryFlag.attrSetStyle("background-position: 0 -%spx" %(entity.SeqID*80) )
        # contentslst = [], attributes='',caption = False, headerlst = [], footerlst= [], tagColums=True, contentsStr=None
        Results=[    
                    [ entity.Name, countryFlag],  # NMhtml.img( "%s%s%s%s%s" %("http://",  req.host ,  "/api/en/countries/flag/",entity.CC, ".png") )], 
                    [NMhtml.img(mapUrl)],  
                    ['Capital:', "N/A" if entity.Capital is None else EntCapital.Name],
                    ['Code ISO 2 :', entity.CC],
                    ['Code ISO Num :', str(entity.CCisoN)], 
                    ['Code ISO 3 :', entity.CCiso3], 
                    ['Code FIPS :', entity.CCfips],
                    ['Tel Prefix :', entity.CCtel],
                    ['Center&#176; :',  "<georss:point>%+.2f %+.2f</georss:point>" %(entity.GeoLat, entity.GeoLon) ], 
                    #['Coordinates Center :', frmtF([entity.GeoLat,  entity.GeoLon]) ]
                    # "<georss:box>%.2f%.2f%.2f%.sf</georss:box>" %(entity.RectW, entity.RectN,   entity.RectE, entity.RectS)
                    ['Rectangle &deg :', "<georss:box>%+.2f %+.2f %+.2f %+.2f</georss:box>" %(entity.RectW, entity.RectN,   entity.RectE, entity.RectS)   ],
                    #['Coordinates<br>Rectangle :', frmtF([entity.RectW, entity.RectN,   entity.RectE, entity.RectS])  ], 
                    [NMhtml.a(infoTitle,"","http://www.geognos.com/geo/en/cc/%s.html" %(entity.CC.lower()), "_blank", infoTitle )] 
                ] 

        tbl= NMhtml.table(Results)
        tb=tbl.body
        tb[0].attrAppendClass('gn-name')
        #tb[1].attrAppendClass('gn-flag')
        tb[1].attrAppendClass('gn-map')
        tb[2].attrAppendClass('gn-capital')
        tb[3].attrAppendClass('gn-iso2')
        tb[4].attrAppendClass('gn-isoN')
        tb[5].attrAppendClass('gn-iso3')
        tb[6].attrAppendClass('gn-fips')
        tb[7].attrAppendClass('gn-TelPref') 
        tb[8].attrAppendClass('gn-GeoCenter')
        tb[9].attrAppendClass('gn-GeoRectangle') 
        tb[10].attrAppendClass('gn-link')
        tb[1][0].attrSet('colspan', "2") 
        tb[10][0].attrSet('colspan', "2")
        tbl.attrSetClass("gn-tbl-country")
        return tbl
    # table, th, td {border: 1px solid black;}
    style=  """ 
            .gn-map img {width:100%;heigh:200px}
            .gn-flag {background-image:url('/media/flags/world-countries-flags-160X80.png');height:80px;width:160px;}
            """    
    style= NMhtml.style(style)
    rt=NMhtml.div(style) 
    rt.attrSetClass("geognos-div-countries")
    if isinstance(entity, mdlsCntrs.cntr):
        rt.insertContents(entityHtml(entity) ) 
    else: 
        entity=[item for item in entity]
        entity.sort(cmp=lambda x,y: cmp(x.Name, y.Name) ) 
        for  entity in entity:
            if entity.CC != "AP":
                rt.insertContents(entityHtml(entity))
    return rt()

def respJson(frmt,Results="", StatusCode=200, StatusMsg="OK"):  
    global simplejson
    if simplejson is None:from django.utils import simplejson 
    Results=simplejson.dumps({"StatusCode": StatusCode, "StatusMsg": StatusMsg, "Results":Results}).replace('\\/','/') 
    #see http://stackoverflow.com/questions/610205/yahoo-pipes-simplejson-and-slashes for escaping /
    if frmt == 'jsonp':Results= '%s(%s)' % ('callback', Results)  
    return Results 

 
class RHapiCC(webapp.RequestHandler):  
    def setCashe(self): 
        # more caching here : http://stackoverflow.com/questions/2185449/images-caching-in-browser-app-engine-patch-aplication                    
        self.response.headers['Cache-Control']= "public, max-age=36000, s-maxage=36000"
        self.response.headers['Last-Modified']= "Sun, 24 Oct 2010 03:00:00 GMT"
        self.response.headers['Expires']=       "Mon, 25 Oct 2010 03:00:00 GMT" 
    def respJsonDel(self,frmt,Results="", StatusCode=200, StatusMsg="OK"):  
        global simplejson
        if simplejson is None:from django.utils import simplejson 
        Results=simplejson.dumps({"StatusCode": StatusCode, "StatusMsg": StatusMsg, "Results":Results}).replace('\\/','/') 
        #see http://stackoverflow.com/questions/610205/yahoo-pipes-simplejson-and-slashes for escaping /
        if frmt == 'jsonp':Results= '%s(%s)' % ('callback', Results)  
        return Results
        
    def setContheaders(self, frmt):
        if frmt=='json' or frmt == 'jsonp':
            self.response.headers['Content-Type']="text/javascript" 
            self.response.headers['mimetype'] ="application/json"
        elif frmt=='png':
            self.response.headers['Content-Type']='image/png' 
        elif frmt== 'xml':  
            self.response.headers['mimetype'] ="application/xml"  
    def get(self,  what, cc,  frmt):    
        def entityTojson():
            rt=entity.json(True)
            rt['CountryInfo']="http://www.geognos.com/geo/en/cc/%s.html" %(entity.CC.lower())
            return rt
        
        cashe3RHDKey="api/%s/%s/%s" %(what, cc, frmt)
        RespResults=cashe3RHD.get (cashe3RHDKey) # (self.request.path_info)   
        if RespResults is None:     #Temporary
            global mdlsCntrs
            if mdlsCntrs is None: import mdlsCntrs  
            if logging:logging.info("cache Fail")   
            if what=='flag': 
                entity= mdlsCntrs.cntrAux.getByKey(cc) 
                if not entity is None:RespResults=entity.Flag160X80
            else: 
                entity = mdlsCntrs.cntr.all() if cc=="all" else mdlsCntrs.cntr.getByKey(cc) 
                if entity is None:
                    if frmt=='json' or frmt=='jsonp':
                        ErrorResults= respJson(frmt,None, StatusCode=400, StatusMsg="Country Not Found") 
                else :
                    if frmt=='json' or frmt=='jsonp':
                        if isinstance(entity, mdlsCntrs.cntr):
                            RespResults=entityTojson()  
                        else:
                            RespResults={}
                            for entity in entity:RespResults[entity.CC]=entityTojson() 
                        RespResults= respJson(frmt, RespResults)  
                    elif frmt=="xml":  
                        RespResults = entity.xml()  
                    elif frmt=="html":
                        RespResults=makeHtml(entity, self.request)  
            if RespResults is not None: cashe3RHD.set(cashe3RHDKey, RespResults) #  memcache.set(self.request.path_info, RespResults) 
        if RespResults is None:
            self.response.set_status(400)
            if frmt=='json' or frmt=='jsonp':
                self.setContheaders(frmt)
                self.response.out.write(ErrorResults)    
        else: 
            self.setContheaders(frmt)            
            self.response.out.write(RespResults)  
            
class RHapiCC_old(webapp.RequestHandler):  
    def resp(self,frmt,Results="", StatusCode=200, StatusMsg="OK"):  
        self.response.set_status(StatusCode)
        self.setContheaders(frmt)
        if frmt=='json' or frmt == 'jsonp': 
            global simplejson
            if simplejson is None:from django.utils import simplejson 
            Results=simplejson.dumps({"StatusCode": StatusCode, "StatusMsg": StatusMsg, "Results":Results}).replace('\\/','/') 
            #see http://stackoverflow.com/questions/610205/yahoo-pipes-simplejson-and-slashes for escaping /
            if frmt == 'jsonp':Results= '%s(%s)' % ('callback', Results)
        elif frmt =='html':
            pass 
        #else: no need # its set by AppEngine Default - self.response.headers['Content-Type']="text/html; charset=utf-8"
        self.response.out.write(Results)  
        return Results 
    def setContheaders(self, frmt):
        if frmt=='json' or frmt == 'jsonp':
            self.response.headers['Content-Type']="text/javascript" 
            self.response.headers['mimetype'] ="application/json"
        elif frmt=='png':
            self.response.headers['Content-Type']='image/png' 
        elif frmt== 'xml':  
            self.response.headers['mimetype'] ="application/xml" 
    def get(self,  what, cc,  frmt):  
        casheVal= memcache.get(self.request.path_info) 
        if casheVal is None:
            global mdlsCntrs
            if mdlsCntrs is None: import mdlsCntrs 
            global logging
            if logging is None: import logging
            logging.info("MCache Fail")   
            if what=='flag': 
                entity= mdlsCntrs.cntrAux.getByKey(cc) 
                if entity is None:self.resp(frmt,Results="", StatusCode=400, StatusMsg="")
                else:Results=self.resp(frmt,Results=entity.Flag160X80)  
            else:    
                entity = mdlsCntrs.cntr.getByKey(cc) 
                if entity is None:self.resp(frmt,Results="", StatusCode=400, StatusMsg="Not Found")
                elif frmt=='json' or frmt=='jsonp':
                    Results=entity.json(True)
                    Results['CountryInfo']="http://www.geognos.com/geo/en/cc/%s.html" %(entity.CC.lower())
                    Results= self.resp(frmt,Results)
                   
                elif frmt=="xml": Results = self.resp(frmt,Results=entity.to_xml() )
                elif frmt=="html": 
                    Results=makeHtml(entity, self.request)
                    Results = self.resp(frmt,Results)
                else: Results=self.resp(frmt,Results=repr(entity) ) 
            if entity is None:pass
            else:memcache.set(self.request.path_info, Results )
        else: 
            self.setContheaders(frmt)            
            self.response.out.write(casheVal)  
        if False: #not entity is None: 
            # more caching here : http://stackoverflow.com/questions/2185449/images-caching-in-browser-app-engine-patch-aplication                    
            self.response.headers['Cache-Control']= "public, max-age=36000, s-maxage=36000"
            self.response.headers['Last-Modified']= "Sun, 24 Oct 2010 03:00:00 GMT"
            self.response.headers['Expires']=       "Mon, 25 Oct 2010 03:00:00 GMT"   
    
class RHapiAll(RHapiCC): 
    def get(self, frmt):
        RespResults= memcache.get(self.request.path_info)  
        if RespResults is None:
            self.doLazyImports()
            logging.info("MCache Fail") 
            mdlsCntrs.cntr.all() 
            
class RHapiIP(RHapiCC): 
    def get(self,  what, ip,  frmt): 
        if ip=='_':ip=self.request.remote_addr 
        ipNum= modelsIP.NMinet.IPencode(ip)
        if ipNum is None:self.resp(frmt,Results="", StatusCode=400, StatusMsg="IP not Found in Geo DB")   
        else:    
            cc=modelsIP.ipv4.getItemFromIpInt(ipNum)
            if  cc is None: 
                if frmt=='json' or frmt=='jsonp':
                    memcacheNoneKey="RHapiCC_None" 
                    RespResults=memcache.get(memcacheNoneKey)
                    if RespResults is None:
                        RespResults= respJson(frmt,None, StatusCode=400, StatusMsg="CountryCodeNotFound")
                        memcache.set(memcacheNoneKey, RespResults)
                else: RespResults="CountryCodeNotFound"
                self.setContheaders(frmt)
                self.response.set_status(400)
                self.response.out.write(RespResults) 
                return
            else:
                if what == 'cc':
                    RespResults= respJson(frmt,Results=cc.cc, StatusCode=200, StatusMsg="OK") 
                    self.setContheaders(frmt)
                    self.response.out.write(RespResults)
                else:
                    RHapiCC.get(self, what, cc.cc, frmt)    
       
#(r"/", rootRQH ),  
#      (r"(.*)", test)], 

application = webapp.WSGIApplication(
                                   [ 
                                    (r"/api/en/countries/(info|flag)/([A-Z]{2}|all)\.(json|jsonp|xml|html|png)", RHapiCC),
                                    #(r"/api/en/countries/(info|flag)/all\.(json|jsonp)", RHapiAll),
                                    (r"/api/en/countries/(info|flag|cc)/(\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}|_)\.(json|jsonp|xml|html|png)", RHapiIP)      
                                    ],
                                     debug=False)
def main(): 
    run_wsgi_app(application)
    
if __name__ == "__main__":
    main()